#pragma once
#include "OSHeaders.h"
#ifndef WIN32
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/tcp.h> 
#endif


class Socket
{
public:
    Socket(UInt32 inSocketType);
    ~Socket();
    enum
    {
        kInvalidFileDesc = -1,   //int
    };
    enum
    {
        kBlockingSocketType = 0,
        kNonBlockingSocketType = 0x0001,
        kBound = 0x0004,
        kConnected = 0x0008
    };
    OS_Error    Open(int theType);
    OS_Error    Bind(UInt32 addr, UInt16 port);
    //OS_Error    Bind(const char *addr, UInt16 port);

    void InitNonBlocking(int inFileDesc);
    void ReuseAddr();
    void Cleanup();
    void NoDelay();
    void KeepAlive();
    void            SetSocketBufSize(UInt32 inNewSize);

    // Returns an error if the socket buffer size is too big
    OS_Error        SetSocketRcvBufSize(UInt32 inNewSize);

    //Returns: QTSS_FileNotOpen, QTSS_NoErr, or POSIX errorcode.
    OS_Error    Send(const char* inData, const UInt32 inLength, UInt32* outLengthSent);

    //Reads some data.
    //Returns: QTSS_FileNotOpen, QTSS_NoErr, or POSIX errorcode.
    OS_Error    Read(void *buffer, const UInt32 length, UInt32 *rcvLen);

    //You can query for the socket's state
    Bool16  IsConnected() { return (Bool16)(m_u32State & kConnected); }
    Bool16  IsBound() { return (Bool16)(m_u32State & kBound); }
    SInt32  GetFD() { return m_s32FileDesc; }
    //WriteV: same as send, but takes an iovec
    //Returns: QTSS_FileNotOpen, QTSS_NoErr, or POSIX errorcode.
    OS_Error        WriteV(const struct iovec* iov, const UInt32 numIOvecs, UInt32* outLengthSent);

protected:

    SInt32 m_s32FileDesc;
    UInt32 m_u32State;

    struct sockaddr_in  fLocalAddr;
    struct sockaddr_in  fDestAddr;
};

